package org.study.swing.study01.table;

import lombok.*;
import org.study.swing.study01.util.DBUtil;

import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.*;
import java.util.Vector;

/**
 * 数据查询和分页处理
 * 参考 https://blog.csdn.net/m0_61495539/article/details/134969062
 * * 参考 https://blog.csdn.net/hitmengfanchao/article/details/137148148
 *
 * @author doveylovey
 * @version v1.0.0
 * @email 1135782208@qq.com
 * @date 2024年11月12日
 */
public class TablePageDemo02_2 extends JFrame {
    public static void main(String[] args) {
        new TablePageDemo02_2();
    }

    // 分页：定义两个变量
    // 当前是第几页
    @Setter
    @Getter
    private int pageNum = 1;
    // 一页显示多少条数据
    private int pageSize = 3;

    // 北边的面板
    JPanel northPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
    JButton addButton = new JButton("添加");
    JButton updateButton = new JButton("修改");
    JButton deleteButton = new JButton("删除");
    JTextField searchTxt = new JTextField(15);
    JButton queryButton = new JButton("查询");
    // 南边的面板
    JPanel southPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
    JButton preButton = new JButton("上一页");
    JButton nextButton = new JButton("下一页");
    // 首先实例化对象
    MainViewTable mainViewTable = new MainViewTable();

    public TablePageDemo02_2() {
        queryButton.addActionListener(new MainViewHandler(this));
        // 上一页和下一页加上监听事件
        preButton.addActionListener(new MainViewHandler(this));
        nextButton.addActionListener(new MainViewHandler(this));

        Container contentPane = super.getContentPane();
        this.layoutNorth(contentPane);
        this.layoutCenter(contentPane);
        this.layoutSouth(contentPane);

        super.setTitle("Java Swing 表格分页示例");
        super.setBounds(100, 100, 1000, 400);
        // 将窗口居中显示在屏幕上
        super.setLocationRelativeTo(null);
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        super.setVisible(true);
    }

    private void layoutNorth(Container contentPane) {
        northPanel.add(addButton);
        northPanel.add(updateButton);
        northPanel.add(deleteButton);
        northPanel.add(searchTxt);
        northPanel.add(queryButton);
        contentPane.add(northPanel, BorderLayout.NORTH);
    }

    private void layoutSouth(Container contentPane) {
        southPanel.add(preButton);
        southPanel.add(nextButton);
        contentPane.add(southPanel, BorderLayout.SOUTH);
    }

    private void layoutCenter(Container contentPane) {
        StudentServiceImpl studentService = new StudentServiceImpl();
        StudentRequest studentRequest = new StudentRequest();
        studentRequest.setPageNum(pageNum);
        studentRequest.setPageSize(pageSize);
        studentRequest.setSearchKey(searchTxt.getText().trim());

        TableDTO tableDTO = studentService.queryStudent(studentRequest);
        Vector<Vector<Object>> data = tableDTO.getData();
        int totalCount = tableDTO.getTotalCount();

        MainViewTableModel mainViewTableModel = MainViewTableModel.assembleModel(data);
        mainViewTable.setModel(mainViewTableModel);
        mainViewTable.renderRule();
        JScrollPane jScrollPane = new JScrollPane(mainViewTable);
        contentPane.add(jScrollPane, BorderLayout.CENTER);

        // 是否显示上一页和下一页按钮
        showPreAndNextButton(totalCount);
    }

    // 是否显示上一页和下一页按钮
    public void showPreAndNextButton(int totalCount) {
        if (pageNum == 1) {
            // preButton.setVisible(false);
            preButton.setEnabled(false);
        } else {
            // preButton.setVisible(true);
            preButton.setEnabled(true);
        }
        int pageCount = 0;
        if (totalCount % pageSize == 0) {
            pageCount = totalCount / pageSize;
        } else {
            pageCount = (totalCount / pageSize) + 1;
        }
        if (pageCount == pageNum) {
            // nextButton.setVisible(false);
            nextButton.setEnabled(false);
        } else {
            // nextButton.setVisible(true);
            nextButton.setEnabled(true);
        }
    }

    public void reloadTable() {
        StudentServiceImpl studentService = new StudentServiceImpl();
        StudentRequest studentRequest = new StudentRequest();

        studentRequest.setPageNum(pageNum);
        studentRequest.setPageSize(pageSize);
        studentRequest.setSearchKey(searchTxt.getText().trim());

        TableDTO tableDTO = studentService.queryStudent(studentRequest);
        Vector<Vector<Object>> data = tableDTO.getData();
        int totalCount = tableDTO.getTotalCount();

        // 更新
        MainViewTableModel.updateModel(data);
        // 查询之后，需要再调用一下渲染的方法
        mainViewTable.renderRule();
        // 是否显示上一页和下一页按钮
        showPreAndNextButton(totalCount);
    }

    @Data
    static class StudentRequest {
        private int pageNum;
        private int pageSize;
        //  搜索关键字
        private String searchKey;
        // 控制从第几页开始
        private int startPageNum;

        public int getStartPageNum() {
            return (pageNum - 1) * pageSize;
        }
    }

    @Data
    static class TableDTO {
        private Vector<Vector<Object>> data;
        private int totalCount;
    }

    interface StudentService {
        TableDTO queryStudent(StudentRequest studentRequest);
    }

    static class StudentServiceImpl implements StudentService {
        @Override
        public TableDTO queryStudent(StudentRequest studentRequest) {
            StringBuilder sql = new StringBuilder();
            sql.append("select * from t_student ");
            if (studentRequest.getSearchKey() != null && !"".equals(studentRequest.getSearchKey().trim())) {
                sql.append(" where name like '%" + studentRequest.getSearchKey() + "%'");
            }
            sql.append("order by id asc limit ")
                    .append(studentRequest.getStartPageNum())
                    .append(",")
                    .append(studentRequest.getPageSize());
            // 执行
            Connection connection = null;
            PreparedStatement preparedStatement = null;
            ResultSet resultSet = null;
            TableDTO tableDTO = new TableDTO(); // 返回的数据
            try {
                connection = DBUtil.getConnection();
                preparedStatement = connection.prepareStatement(sql.toString());
                // 执行查询返回结果集
                resultSet = preparedStatement.executeQuery();
                // 查询记录
                Vector<Vector<Object>> queryDatas = fillTableData(resultSet);
                tableDTO.setData(queryDatas);
                sql.setLength(0);
                sql.append("select count(*) from t_student ");
                if (studentRequest.getSearchKey() != null && !"".equals(studentRequest.getSearchKey().trim())) {
                    sql.append(" where name like '%" + studentRequest.getSearchKey() + "%'");
                }
                preparedStatement = connection.prepareStatement(sql.toString());
                resultSet = preparedStatement.executeQuery();
                while (resultSet.next()) {
                    int count = resultSet.getInt(1);
                    tableDTO.setTotalCount(count);
                }
                return tableDTO;

            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                DBUtil.close(resultSet, preparedStatement, connection);
            }
            return null;
        }

        private static Vector<Vector<Object>> fillTableData(ResultSet resultSet) throws SQLException {
            Vector<Vector<Object>> data = new Vector<>();
            while (resultSet.next()) {
                // 遍历查询的每一条记录
                Vector<Object> oneRecord = new Vector<>();
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                Date birthday = resultSet.getDate("birthday");
                int sex = resultSet.getInt("sex");
                int state = resultSet.getInt("state");
                String address = resultSet.getString("address");
                int classId = resultSet.getInt("class_id");

                oneRecord.addElement(id);
                oneRecord.addElement(name);
                oneRecord.addElement(birthday);
                oneRecord.addElement("homeTown");
                oneRecord.addElement(sex);
                oneRecord.addElement(state);
                oneRecord.addElement(address);
                oneRecord.addElement(classId);

                data.addElement(oneRecord);
            }
            return data;
        }
    }

    static class MainViewTableModel extends DefaultTableModel {
        static Vector<String> column = new Vector<>() {{
            this.addElement("编号");
            this.addElement("姓名");
            this.addElement("学号");
            this.addElement("家乡");
            this.addElement("语文");
            this.addElement("数学");
            this.addElement("英语");
            this.addElement("总分");
        }};

        public MainViewTableModel() {
            super(null, column);
        }

        // 饿汉式
        private static MainViewTableModel mainViewTableModel = new MainViewTableModel();

        public static MainViewTableModel assembleModel(Vector<Vector<Object>> data) {
            // 组装数据  -> 肯定有返回对象，即要设置返回类型
            mainViewTableModel.setDataVector(data, column);
            return mainViewTableModel;
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            return false;
        }

        // 添加get方法 获取列名
        public static Vector<String> getColumn() {
            return column;
        }

        public static void updateModel(Vector<Vector<Object>> data) {
            mainViewTableModel.setDataVector(data, column);
            // 更新不需要返回值的
        }
    }

    static class MainViewTable extends JTable {
        public MainViewTable() {
            // 设置表头的样式
            JTableHeader tableHeader = getTableHeader();
            tableHeader.setFont(new Font("微软雅黑", Font.BOLD, 18));
            tableHeader.setForeground(Color.red);
            // 设置表格体的样式
            setFont(new Font("微软雅黑", Font.PLAIN, 14));
            setForeground(Color.black);
            // 设置表格线颜色
            setGridColor(Color.black);
            // 设置行高
            setRowHeight(30);
            // 设置多行选择
            getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        }

        public void renderRule() {
            // 设置表格列的渲染方式
            Vector<String> column = MainViewTableModel.getColumn();
            MainViewCellRender mainViewCellRender = new MainViewCellRender();
            for (int i = 0; i < column.size(); i++) {
                TableColumn c = getColumn(column.get(i));
                c.setCellRenderer(mainViewCellRender);
                if (i == 0) {
                    c.setPreferredWidth(10);
                    c.setResizable(false);
                }
            }
        }
    }

    static class MainViewCellRender extends DefaultTableCellRenderer {
        // 在每一行每一列显示之前都会调用
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            if (row % 2 == 0) {
                setBackground(Color.LIGHT_GRAY);
            } else {
                setBackground(Color.WHITE);
            }
            // 设置水平居中
            setHorizontalAlignment(DefaultTableCellRenderer.CENTER);
            return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        }
    }

    static class MainViewHandler implements ActionListener {
        private TablePageDemo02_2 mainView;

        public MainViewHandler(TablePageDemo02_2 mainView) {
            this.mainView = mainView;
        }
        // 将传入的 MainView 对象赋值给 MainViewHandler 类中的私有变量 mainView。通过传入 MainView 对象并在构造函数中进行赋值，MainViewHandler 类就能够直接访问传入的 MainView 对象，从而可以对其进行操作。

        @Override
        public void actionPerformed(ActionEvent e) {
            // 通过 getSource() 方法获取触发事件的组件，并将其转换为 JButton 对象。
            // 然后，通过 getText() 方法获取该按钮的文本内容，并将其存储在 text 变量中。
            JButton jButton = (JButton) e.getSource();
            String text = jButton.getText();
            if ("增加".equals(text)) {

            } else if ("修改".equals(text)) {

            } else if ("删除".equals(text)) {

            } else if ("查询".equals(text)) {
                // 查询的时候需要设置pageNum为1
                mainView.setPageNum(1);
                mainView.reloadTable();
            } else if ("上一页".equals(text)) {
                mainView.setPageNum(mainView.getPageNum() - 1);
                mainView.reloadTable();
            } else if ("下一页".equals(text)) {
                mainView.setPageNum(mainView.getPageNum() + 1);
                mainView.reloadTable();
            }
        }
    }
}
